Skip to main content

Pesquisa — Análise de Código: CRMBonus na API Checkout

Data: 2026-05-15
Contexto: Task #193232 — Análise do fluxo de integração CRMBonus
Fonte: coezzion-service-checkout/src/


Interface do Serviço

Arquivo: src/Checkout.Infraestructure/Integrations/CrmBonus/ICrmBonusService.cs

public interface ICrmBonusService
{
Task<HttpResponseMessage> DebitCrmBonusAsync(CrmBonutDTO crmBonus, int storeId);
Task<HttpResponseMessage> FinishCrmBonusAsync(CrmBonutDTO crmBonus, int storeId, int paymentId);
Task<HttpResponseMessage> CancelCrmBonusAsync(CancelBonusDTO cancelCrmBonus, int storeId, int paymentId);
}

DTOs

Arquivo: src/Checkout.Domain/DTO/CrmBonus/CrmBonutDTO.cs

// Usado em DebitCrmBonusAsync e FinishCrmBonusAsync
public class CrmBonutDTO
{
public int user_Id { get; set; }
public decimal valor_bruto { get; set; }
public decimal bonus_resgatado { get; set; }
public string ids_bonus { get; set; }
public string ticket { get; set; } // = paymentIdComplex (código composto do pedido)
public string? campanha { get; set; } // "-1" se campanha == 0, senão "0"
}
// Usado em CancelCrmBonusAsync
public class CancelBonusDTO
{
public string num_pedido { get; set; } // = paymentIdComplex
public bool used_bonus { get; set; } // true = pós-finalização; false = pré-finalização
}

Arquivo: src/Checkout.Domain/DTO/CrmBonus/CrmBonusConfig.cs

public class CrmBonusConfig
{
public string BaseURL { get; set; }
public string Authorization { get; set; }
}
// Configurado via appsettings na seção: Apis:CrmBonus

Implementação do Serviço

Arquivo: src/Checkout.Infraestructure/Integrations/CrmBonus/CrmBonusService.cs

Mecanismo de Autenticação

Dois headers são enviados em cada requisição:

HeaderValor
AuthorizationValor fixo da configuração CrmBonusConfig.Authorization
CodempresaBase64(tokenCrm)tokenCrm obtido em runtime via IStorePaymentsRepository.GetTokenCrmByIdAsync(storeId)

Validação de Resposta — IsCrmBonusValidResponse

Extension method que define o critério de sucesso:

// Resposta válida = HTTP 2xx E body JSON com { "status": true }
public static bool IsCrmBonusValidResponse(this HttpResponseMessage response)

Ambas as condições são obrigatórias. Uma resposta HTTP 200 com "status": false no body é considerada inválida.

Comportamento de Erros por Operação

OperaçãoComportamento em erro
DebitCrmBonusAsyncValida bonus_resgatado > 0 antes de enviar; loga resposta
FinishCrmBonusAsyncCaptura HttpRequestException com log detalhado; não lança exceção para cima
CancelCrmBonusAsyncLoga a ação após a resposta

Mapa Completo de Callers

DebitCrmBonusAsync — Reserva de bônus

CallerArquivoCondição de guarda
CreatePaymentCommandHandlerApplication/Messages/Commands/CreateCommands/CreatePaymentCommandHandler.cscart.CrmBonus != null

Contexto: Chamado ao criar o pedido (Handle(CreatePaymentByAppCommand)). O debit ocorre antes de qualquer processamento de pagamento. Uma falha não bloqueia a criação do pedido — é logada via ILogQueueService.


FinishCrmBonusAsync — Efetivação do consumo

CallerArquivoCondição de guarda
PosCaptureServiceApplication/Services/PosCaptureService.cscart.CrmBonus != null && !string.IsNullOrEmpty(cart.CrmBonus.IdsBonus)

Contexto: Passo 4 de ExecutePosCapture. Chamado após captura bem-sucedida do pagamento.

PosCaptureService é invocado por:

  • AntiFraudWebhookService (aprovação pelo antifraude)
  • PagarMeCaptureService (captura PagarMe)
  • OrderCommandHandler (captura Braspag)
  • WebhookBraspagService, PagarMeCreditCardService, PagarMePixService, FinishPaymentService

Montagem do DTO em PosCaptureService:

var crmBonus = CrmBonutDTO.CreateFromCrmBonus(
cart.CrmBonus.UserId,
cart.CrmBonus.Total,
cart.CrmBonus.RescuedBonus,
cart.CrmBonus.IdsBonus,
paymentIdComplex,
Convert.ToInt32(cart.GenerateCrmBonus));

CancelCrmBonusAsync — Cancelamento/liberação

CallerArquivoused_bonusCenário
OrderCommandHandlerApplication/Messages/Commands/OrderCommands/OrderCommandHandler.cstrueCancelamento manual do pedido
OrderCommandHandleridemtrueFalha na captura Braspag
AntiFraudWebhookServiceIntegrations/Clearsale/AntiFraudWebhookService.cstrueFalha na captura Braspag pós-aprovação antifraude

Semântica do Parâmetro used_bonus

O parâmetro used_bonus no CancelBonusDTO informa ao CRM&Bonus se o bônus chegou a ser efetivado antes do cancelamento.

ValorSignificadoQuando ocorre no código
trueBônus foi efetivado (finaliza_compra já foi chamado)Cancelamento manual pós-aprovação; falha de captura Braspag pós-aprovação antifraude
falseBônus foi apenas reservado (baixa_bonus chamado, finaliza_compra ainda não)Antifraude recusou; captura PagarMe falhou

Atenção: O código atual em AntiFraudWebhookService envia used_bonus = true para o cenário de falha de captura Braspag — não para rejeição pelo antifraude. Para PagarMe com antifraude reprovado, o cancelamento não é chamado diretamente pelo AntiFraudWebhookService; delega ao PagarMeRefundService.


Inconsistência com Documentação Anterior (crm_analise.md)

O arquivo docs/crm/crm_analise.md contém uma imprecisão:

Afirma: AntiFraudWebhookServiceused_bonus = false quando "o antifraude recusa a transação"

Código real: AntiFraudWebhookService chama CancelCrmBonusAsync com used_bonus = true apenas no fluxo Braspag quando a captura falha (não quando o antifraude recusa). Para PagarMe, a responsabilidade é do PagarMeRefundService.


Condições de Guarda Relevantes

  • DebitCrmBonusAsync: Só é chamado se cart.CrmBonus != null. Internamente, só faz a requisição HTTP se bonus_resgatado > 0.
  • FinishCrmBonusAsync: Só é chamado se cart.CrmBonus != null && !string.IsNullOrEmpty(cart.CrmBonus.IdsBonus).
  • CancelCrmBonusAsync: Só é chamado se cart.CrmBonus != null (verificado em CancelBonusAsync privado do OrderCommandHandler).

Campo paymentIdComplex

O identificador ticket/num_pedido enviado ao CRM&Bonus é um código composto, não o ID numérico direto do pedido. É gerado pelo serviço ICreateCodePaymentsForIntegrations.CreateCodePayment(orderId).